From 12ea00aa1898e33a467e2d8e18b6ebad43a181f3 Mon Sep 17 00:00:00 2001
From: Golubev Alexander <fatzer2@gmail.com>
Date: Thu, 15 Aug 2013 02:08:26 +0400
Subject: [PATCH 2/3] TDE: fix a number of problems

Conflicts:
	art_config.h
---
 ChangeLog             |   2 +
 README                |  14 ++++++
 art_render_gradient.c |  28 ++++++++++++
 art_render_gradient.h |   3 +-
 art_vpath_bpath.c     | 119 ++++++++++++++++++++++++--------------------------
 gen_art_config.sh.in  |   6 +++
 libart-config.in      |  13 +++++-
 testart.c             |   6 +++
 8 files changed, 127 insertions(+), 64 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6861cf3..e274c9c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,5 @@
+*** PLEASE SEE THE GIT COMMIT LOG FOR NEWER CHANGES ***
+
 2009-01-14  Fridrich Strba  <fridrich.strba@bluewin.ch>
 
 	* gen_art_config.c: remove
diff --git a/README b/README
index 882527e..a88ec40 100644
--- a/README
+++ b/README
@@ -17,3 +17,17 @@ For more information about libart, see the web page:
 There's also a libart tutorial available at
 http://www.gnome.org/~mathieu/libart/libart.html
 
+======================================================================
+
+NOTE: The TDE project has take over maintinance of this library,
+starting with the sources from the final upstream release v2.3.21.
+
+This allows the TDE project to resolve remaining issues that cause
+problems or crashes within TDE.
+
+This patched library is only available under the terms of the
+GPL/LGPL, and is NOT for sale by the original author as mentioned
+above, as patch copyright has NOT been transferred to the original
+author and we have no plans to do so.
+
+======================================================================
diff --git a/art_render_gradient.c b/art_render_gradient.c
index bf93c6f..008d61a 100644
--- a/art_render_gradient.c
+++ b/art_render_gradient.c
@@ -30,7 +30,9 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#if 0
 #include <assert.h>
+#endif
 
 /* Hack to find out how to define alloca on different platforms.
  * Modified version of glib/galloca.h.
@@ -203,7 +205,9 @@ calc_color_at (ArtGradientStop *stops,
     }
 
   printf ("WARNING! bad ix %d in calc_color_at() [internal error]\n", ix);
+#if 0
   assert (0);
+#endif
 }
 
 static void
@@ -331,6 +335,7 @@ art_render_gradient_linear_render_8 (ArtRenderCallback *self,
   printf ("Initial ix: %d\n", ix);
 #endif
   
+#if 0
   assert (ix > 0);
   assert (ix < n_stops);
   assert ((stops[ix-1].offset <= offset_fraction + EPSILON) ||
@@ -344,6 +349,17 @@ art_render_gradient_linear_render_8 (ArtRenderCallback *self,
   assert ((offset_fraction != stops[ix].offset) ||
 	  (d_offset <= 0.0));
   */
+#else
+  if (!( (ix > 0) && (ix < n_stops)
+         && ((stops[ix-1].offset <= offset_fraction + EPSILON) ||
+             ((stops[ix].offset > (1.0 - EPSILON))
+              && (offset_fraction < EPSILON /* == 0.0*/)))
+         && (offset_fraction <= stops[ix].offset)))
+  {
+    printf ("art_render_gradient.c:%d: Old assert() failed!\n", __LINE__);
+    return;
+  }
+#endif
   
   while (width > 0)
     {
@@ -663,6 +679,18 @@ art_render_gradient_radial_render (ArtRenderCallback *self, ArtRender *render,
 	z = b_a + sqrt (rad);
       else
 	z = b_a;
+
+      if (gradient->spread == ART_GRADIENT_PAD)
+	z = z;
+      else if (gradient->spread == ART_GRADIENT_REPEAT)
+	z = z - floor (z);
+      else /* (gradient->spread == ART_GRADIENT_REFLECT) */
+	{
+	  double tmp;
+
+	  tmp = z - 2 * floor (0.5 * z);
+	  z = tmp > 1 ? 2 - tmp : tmp;
+	}
       art_render_gradient_setpix (render, bufp, n_stops, stops, z);
       bufp += pixstride;
       b_a += db_a;
diff --git a/art_render_gradient.h b/art_render_gradient.h
index ef5da95..7e8e0c8 100644
--- a/art_render_gradient.h
+++ b/art_render_gradient.h
@@ -52,14 +52,15 @@ struct _ArtGradientLinear {
   double a;
   double b;
   double c;
-  ArtGradientSpread spread;
   int n_stops;
   ArtGradientStop *stops;
+  ArtGradientSpread spread;
 };
 
 struct _ArtGradientRadial {
   double affine[6]; /* transforms user coordinates to unit circle */
   double fx, fy;    /* focal point in unit circle coords */
+  ArtGradientSpread spread;
   int n_stops;
   ArtGradientStop *stops;
 };
diff --git a/art_vpath_bpath.c b/art_vpath_bpath.c
index 3f9afe7..2459f23 100644
--- a/art_vpath_bpath.c
+++ b/art_vpath_bpath.c
@@ -123,18 +123,6 @@ art_vpath_render_bez (ArtVpath **p_vpath, int *pn, int *pn_max,
 		      double x3, double y3,
 		      double flatness)
 {
-  double x3_0, y3_0;
-  double z3_0_dot;
-  double z1_dot, z2_dot;
-  double z1_perp, z2_perp;
-  double max_perp_sq;
-
-  double x_m, y_m;
-  double xa1, ya1;
-  double xa2, ya2;
-  double xb1, yb1;
-  double xb2, yb2;
-
   /* It's possible to optimize this routine a fair amount.
 
      First, once the _dot conditions are met, they will also be met in
@@ -157,70 +145,79 @@ art_vpath_render_bez (ArtVpath **p_vpath, int *pn, int *pn_max,
      just that I have this undying quest for more speed...
 
   */
-
-  x3_0 = x3 - x0;
-  y3_0 = y3 - y0;
-
-  /* z3_0_dot is dist z0-z3 squared */
-  z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0;
-
-  if (z3_0_dot < 0.001)
+  do
     {
-      /* if start and end point are almost identical, the flatness tests
-       * don't work properly, so fall back on testing whether both of
-       * the other two control points are the same as the start point,
-       * too.
-       */
-      if (hypot(x1 - x0, y1 - y0) < 0.001
-	  && hypot(x2 - x0, y2 - y0) < 0.001)
-	  goto nosubdivide;
-      else
-	  goto subdivide;
-    }
+    /* don't subdivide inside this */
+    double x3_0, y3_0;
+    double z3_0_dot;
+    double z1_dot, z2_dot;
+    double z1_perp, z2_perp;
+    double max_perp_sq;
 
-  /* we can avoid subdivision if:
+    x3_0 = x3 - x0;
+    y3_0 = y3 - y0;
 
-     z1 has distance no more than flatness from the z0-z3 line
+    /* z3_0_dot is dist z0-z3 squared */
+    z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0;
 
-     z1 is no more z0'ward than flatness past z0-z3
+    if (z3_0_dot > 0.001)
+      {
+       /* we can avoid subdivision if:
 
-     z1 is more z0'ward than z3'ward on the line traversing z0-z3
+          z1 has distance no more than flatness from the z0-z3 line
 
-     and correspondingly for z2 */
+          z1 is no more z0'ward than flatness past z0-z3
 
-  /* perp is distance from line, multiplied by dist z0-z3 */
-  max_perp_sq = flatness * flatness * z3_0_dot;
+          z1 is more z0'ward than z3'ward on the line traversing z0-z3
 
-  z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0;
-  if (z1_perp * z1_perp > max_perp_sq)
-    goto subdivide;
+          and correspondingly for z2 */
 
-  z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0;
-  if (z2_perp * z2_perp > max_perp_sq)
-    goto subdivide;
+        /* perp is distance from line, multiplied by dist z0-z3 */
+        max_perp_sq = flatness * flatness * z3_0_dot;
 
-  z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0;
-  if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq)
-    goto subdivide;
+        z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0;
+        if (z1_perp * z1_perp > max_perp_sq)
+          break;
 
-  z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0;
-  if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq)
-    goto subdivide;
+        z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0;
+        if (z2_perp * z2_perp > max_perp_sq)
+          break;
 
-  if (z1_dot + z1_dot > z3_0_dot)
-    goto subdivide;
+        z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0;
+        if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq)
+          break;
 
-  if (z2_dot + z2_dot > z3_0_dot)
-    goto subdivide;
+        if (z1_dot + z1_dot > z3_0_dot)
+          break;
 
-      
- nosubdivide:
-  /* don't subdivide */
-  art_vpath_add_point (p_vpath, pn, pn_max,
-		       ART_LINETO, x3, y3);
-  return;
+        z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0;
+        if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq)
+          break;
 
- subdivide:
+        if (z2_dot + z2_dot > z3_0_dot)
+          break;
+      }
+    else
+      {
+      /* if start and end point are almost identical, the flatness tests
+       * don't work properly, so fall back on testing whether both of
+       * the other two control points are the same as the start point,
+       * too.
+       */
+        if (hypot(x1 - x0, y1 - y0) > 0.001
+            || hypot(x2 - x0, y2 - y0) > 0.001)
+            break;
+      }
+
+      art_vpath_add_point (p_vpath, pn, pn_max,
+                           ART_LINETO, x3, y3);
+      return;
+    } while (0);
+  double x_m, y_m;
+  double xa1, ya1;
+  double xa2, ya2;
+  double xb1, yb1;
+  double xb2, yb2;
 
   xa1 = (x0 + x1) * 0.5;
   ya1 = (y0 + y1) * 0.5;
diff --git a/gen_art_config.sh.in b/gen_art_config.sh.in
index 79843bc..8c525bd 100644
--- a/gen_art_config.sh.in
+++ b/gen_art_config.sh.in
@@ -8,6 +8,9 @@
 
 echo "/* Automatically generated by gen_art_config */"
 echo
+echo "#ifndef _ART_CONFIG_H_"
+echo "#define _ART_CONFIG_H_"
+echo
 echo "#define ART_SIZEOF_CHAR @ART_SIZEOF_CHAR@"
 echo "#define ART_SIZEOF_SHORT @ART_SIZEOF_SHORT@"
 echo "#define ART_SIZEOF_INT @ART_SIZEOF_INT@"
@@ -39,5 +42,8 @@ else
   fi
 fi
 
+echo
+echo "#endif /* _ART_CONFIG_H_ */"
+
 exit 0
 }
diff --git a/libart-config.in b/libart-config.in
index 0a2f3a9..e32f010 100644
--- a/libart-config.in
+++ b/libart-config.in
@@ -3,6 +3,8 @@
 prefix=@prefix@
 exec_prefix=@exec_prefix@
 exec_prefix_set=no
+libs=""
+output_libs=no
 
 usage="\
 Usage: libart-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags]"
@@ -43,8 +45,11 @@ while test $# -gt 0; do
       echo $includes
       ;;
     --libs)
-      libdirs=-L@libdir@
-      echo $libdirs -lart_lgpl_2 -lm
+      libs="$libs -L@libdir@ -lart_lgpl_2"
+      output_libs=yes
+      ;;
+    --static)
+      libs="$libs -lm"
       ;;
     *)
       echo "${usage}" 1>&2
@@ -54,3 +59,7 @@ while test $# -gt 0; do
   shift
 done
 
+if test $output_libs = yes ; then
+    echo $libs
+fi
+
diff --git a/testart.c b/testart.c
index f20b292..994c7ba 100644
--- a/testart.c
+++ b/testart.c
@@ -228,6 +228,7 @@ make_testpat (void)
   art_free (vpath3);
 #else
   svp2 = art_svp_from_vpath (vpath2);
+  art_free (vpath2);
 #endif
 
 #if 1
@@ -361,6 +362,7 @@ test_dist (void)
 			       4,
 			       0.5);
 #endif
+  art_free (vpath);
 
   art_rgb_svp_aa (svp, 0, 0, 512, 512,
 		  0xffe0a0, 0x100040,
@@ -431,10 +433,12 @@ test_render_gradient (art_u8 *buf)
 
   vpath = randstar (50);
   svp = art_svp_from_vpath (vpath);
+  art_free (vpath);
 
   render = art_render_new (0, 0, 512, 512, buf, 512 * 3, 3, 8, ART_ALPHA_NONE,
 			   NULL);
   art_render_svp (render, svp);
+  art_svp_free (svp);
   art_render_gradient_linear (render, &gradient, ART_FILTER_NEAREST);
   art_render_invoke (render);
 
@@ -467,6 +471,7 @@ test_render_rad_gradient (art_u8 *buf)
 
   vpath = randstar (50);
   svp = art_svp_from_vpath (vpath);
+  art_free (vpath);
 
   render = art_render_new (0, 0, 512, 512, buf, 512 * 3, 3, 8, ART_ALPHA_NONE,
 			   NULL);
@@ -489,6 +494,7 @@ test_gradient (void)
 
   vpath = randstar (50);
   svp = art_svp_from_vpath (vpath);
+  art_free (vpath);
 
   for (i = 0; i < n_iter; i++)
     {
-- 
1.8.1.5

